package wsepForum.network.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import wsepForum.domain.ForumDomain;
import wsepForum.logging.ForumLogger;
import wsepForum.logging.ForumLogger.LoggerCategory;


/**
 * A Simple network server to deal with incoming connections from the clients
 * @author Oren Ben-Haim
 *
 */
public class SimpleServer extends Thread {
	/*****************************
	 * MEMBERS                   *
	 *****************************/
	/**
	 * The server socket
	 */
	private ServerSocket serverSocket = null;
	/**
	 * the port we will listen to
	 */
	private int listenPort;
	/**
	 * Main forum domain
	 */
	final private ForumDomain domain;
	/**
	 * if true the connection should disconnect
	 */
	private boolean disconnectFlag = false;

	private IConnectionHandlerFactory factory;

	/*****************************
	 * CONSTRUCTOR               *
	 *****************************/
	/**
	 * @param forumDomain main forum's class
	 */
	public SimpleServer(ForumDomain domain, IConnectionHandlerFactory factory, int listenPort) {
		this.domain = domain;
		this.factory = factory;
		this.listenPort = listenPort;
	}
	/*****************************
	 * METHODS                   *
	 *****************************/
	/**
	 * main server listen loop
	 */
	public void run()
	{
		final ForumLogger logger = ForumLogger.getInstance();
		try
		{
			synchronized(this.domain) {
			this.serverSocket = new ServerSocket(this.listenPort);
			}
			logger.info("Server started Listening...",LoggerCategory.NETWORK);
		}
		catch (IOException e)
		{
			// TODO Change handling
			logger.error("Cannot listen on port " + this.listenPort + " aborting....",LoggerCategory.NETWORK);
			return;
		}
		while (!disconnectFlag)
		{
			try
			{
				Socket socket = this.serverSocket.accept();
				ConnectionHandler<?> chandler = factory.newHandler(socket);
				chandler.start();
			}
			catch (IOException e)
			{
				// TODO Change handling
				if (!e.getMessage().equals("socket closed")) {
				logger.error("Failed to accept on port " + this.listenPort,LoggerCategory.NETWORK);
				}
				else {
					logger.info("Server network socket closed.",LoggerCategory.NETWORK);
				}
			}

		}
	}

	/**
	 * Closes the connection
	 *
	 * @throws IOException
	 *             in problems with connection
	 */
	public void close() throws IOException
	{
		synchronized(this.domain) {
			this.disconnectFlag = true;
			//this.interrupt();
			this.serverSocket.close();
		}
	}

}
